"""
帖子相关API接口
"""

# 导入标准库和第三方库
from fastapi import APIRouter, Depends, HTTPException, Query  # FastAPI相关模块
from sqlalchemy.orm import Session  # SQLAlchemy会话
from sqlalchemy import desc, or_  # SQLAlchemy查询函数
from typing import Optional, List  # 类型提示
from pydantic import BaseModel  # Pydantic数据模型
import json  # JSON处理

# 导入项目内部模块
from database import get_db  # 数据库会话依赖
from models.post import Post, Tag  # 帖子和标签模型
from models.user import User  # 用户模型
from tools.auth import verify_token  # JWT token验证
from tools.response import success_response, error_response  # 响应格式化工具
from tools.observer import post_observer, PostEvent  # 观察者模式


# 创建API路由实例
router = APIRouter(prefix="/api/posts", tags=["posts"])


class PostResponse(BaseModel):
    """帖子响应模型"""
    id: int
    title: str
    content: Optional[str]
    images: List[str]
    author: dict
    tags: List[str]
    category: Optional[str]
    likes: int
    views: int
    comments: int
    collects: int
    created_at: str
    
    class Config:
        from_attributes = True


class PostsListResponse(BaseModel):
    """帖子列表响应模型"""
    posts: List[PostResponse]
    total: int
    page: int
    page_size: int
    has_more: bool


def get_current_user_optional(token: Optional[str] = None):
    """可选的身份验证，如果未登录则返回None"""
    if not token:
        return None
    try:
        payload = verify_token(token)
        return payload
    except:
        return None


@router.get("/categories")
async def get_categories(db: Session = Depends(get_db)):
    """
    获取所有帖子分类
    
    返回:
        包含所有分类的列表
    """
    try:
        # 查询所有不同的分类
        categories = db.query(Post.category).distinct().all()
        
        # 提取分类名称并过滤掉None值
        category_list = [cat[0] for cat in categories if cat[0]]
        
        # 返回成功响应
        return success_response(
            data=category_list,
            msg="分类列表获取成功"
        )
    except Exception as e:
        # 捕获异常并返回错误响应
        return error_response(
            msg=f"获取分类列表失败: {str(e)}",
            code=500
        )


@router.get("", response_model=PostsListResponse)
async def list_posts(
    page: int = Query(1, ge=1),           # 页码，从1开始
    page_size: int = Query(10, le=50),    # 每页大小，最多50条
    category: Optional[str] = None,       # 分类筛选
    search: Optional[str] = None,         # 搜索关键词
    tag: Optional[str] = None,            # 标签筛选
    db: Session = Depends(get_db)         # 数据库会话依赖
):
    """
    获取帖子列表
    
    参数:
        page: 页码
        page_size: 每页条数
        category: 分类筛选
        search: 搜索关键词
        tag: 标签筛选
        
    返回:
        分页的帖子列表
    """
    try:
        # 构造查询
        query = db.query(Post).join(User)
        
        # 应用分类筛选
        if category:
            query = query.filter(Post.category == category)
        
        # 应用搜索筛选
        if search:
            query = query.filter(
                or_(
                    Post.title.contains(search),
                    Post.content.contains(search)
                )
            )
        
        # 应用标签筛选
        if tag:
            query = query.join(Post.tags).filter(Tag.name == tag)
        
        # 按创建时间降序排列
        query = query.order_by(desc(Post.created_at))
        
        # 计算总数
        total = query.count()
        
        # 应用分页
        posts = query.offset((page - 1) * page_size).limit(page_size).all()
        
        # 处理帖子数据
        post_list = []
        for post in posts:
            # 解析图片URL列表
            images = []
            if post.images:
                try:
                    images = json.loads(post.images)
                    # 确保返回的是列表
                    if not isinstance(images, list):
                        images = [images] if images else []
                except (json.JSONDecodeError, TypeError):
                    # 如果不是JSON格式，当作单个URL处理
                    images = [post.images] if post.images else []
            
            # 获取标签名称列表
            tags = [tag.name for tag in post.tags]
            
            # 构造帖子响应数据
            post_data = {
                "id": post.id,
                "title": post.title,
                "content": post.content or "",
                "images": images,
                "author": {
                    "id": post.author.id,
                    "nickname": post.author.nickname or post.author.username,
                    "avatar": post.author.avatar
                },
                "tags": tags,
                "category": post.category,
                "likes": post.likes,
                "views": post.views,
                "comments": post.comments,
                "collects": post.collects,
                "created_at": post.created_at.isoformat() if post.created_at else ""
            }
            post_list.append(post_data)
        
        # 构造响应数据 - 直接返回符合PostsListResponse模型的数据
        # 因为使用了response_model，FastAPI会自动验证和转换
        return {
            "posts": post_list,
            "total": total,
            "page": page,
            "page_size": page_size,
            "has_more": page * page_size < total
        }
    except Exception as e:
        # 捕获异常并抛出HTTP异常
        # 因为使用了response_model，不能返回error_response格式
        # 需要使用HTTPException来正确处理错误
        import traceback
        traceback.print_exc()
        raise HTTPException(
            status_code=500,
            detail=f"获取帖子列表失败: {str(e)}"
        )


@router.get("/{post_id}", response_model=PostResponse)
async def get_post(
    post_id: int, 
    db: Session = Depends(get_db)
):
    """
    获取帖子详情
    
    参数:
        post_id: 帖子ID
        
    返回:
        帖子详情
    """
    try:
        # 查询帖子
        post = db.query(Post).filter(Post.id == post_id).first()
        
        # 检查帖子是否存在
        if not post:
            raise HTTPException(
                status_code=404,
                detail="帖子不存在"
            )
        
        # 增加浏览量（自增）
        post.views += 1
        db.commit()
        
        # 使用观察者模式：触发浏览事件
        view_event = PostEvent(event_type='view', post_id=post_id, user_id=None)
        post_observer.notify(view_event)
        
        # 解析images字段为URL数组
        images = []
        if post.images:
            try:
                images = json.loads(post.images)
                # 确保返回的是列表
                if not isinstance(images, list):
                    images = [images] if images else []
            except (json.JSONDecodeError, TypeError):
                # 如果不是JSON格式，当作单个URL处理
                images = [post.images] if post.images else []
        
        # 关联查询标签名称列表
        tags = [tag.name for tag in post.tags]
        
        # 构建响应数据 - 直接返回符合PostResponse模型的数据
        # 因为使用了response_model，FastAPI会自动验证和转换
        return {
            "id": post.id,
            "title": post.title,
            "content": post.content or "",
            "images": images,
            "tags": tags,
            "category": post.category,
            "likes": post.likes,
            "views": post.views,
            "comments": post.comments,
            "collects": post.collects,
            "author": {
                "id": post.author.id,
                "nickname": post.author.nickname or post.author.username,
                "avatar": post.author.avatar
            },
            "created_at": post.created_at.isoformat() if post.created_at else ""
        }
    except HTTPException:
        # 重新抛出HTTP异常
        raise
    except Exception as e:
        # 捕获异常并抛出HTTP异常
        # 因为使用了response_model，不能返回error_response格式
        # 需要使用HTTPException来正确处理错误
        db.rollback()
        import traceback
        traceback.print_exc()
        raise HTTPException(
            status_code=500,
            detail=f"获取帖子详情失败: {str(e)}"
        )